#include "stdafx.h"
#include <LitEditorMeshConverter.h>
#include <LitCore.h>
#include <LitSceneManager.h>
#include <LitXmlSceneManager.h>
#include <LitFileParser.h>

namespace Lit
{
	namespace Editor
	{
		MeshConverter::Format::Format( const std::string &name, const std::string &extension, bool canImport_, bool canExport_ ) : mName(name), mCanImport(canImport_), mCanExport(canExport_), mExtension( extension ){}
		MeshConverter::Format::~Format(){}

		std::string MeshConverter::Format::eatLeft( const std::string &str, size_t num ){
			return trim(str.substr( num, str.size()-num ));
		}

		std::string MeshConverter::Format::trim( const std::string &str, bool left, bool right ){
			std::string ret(str);
			Ogre::StringUtil::trim( ret, left, right );
			return ret;
		}
		const std::string &MeshConverter::Format::getName() const{
			return mName ;
		}
		
		bool		MeshConverter::Format::canImport() const{return mCanImport;}
		bool		MeshConverter::Format::canExport() const{return mCanExport;}

		const std::string &MeshConverter::Format::getExtension() const{ return mExtension; }
			
		MeshConverter::MeshConverter()
		{
		}
		MeshConverter::~MeshConverter()
		{
			clearFormats();
		}
		std::vector<MeshConverter::Format*>& MeshConverter::getFormats()
		{
			return mFormats;
		}
		const std::vector<MeshConverter::Format*>& MeshConverter::getFormats() const
		{
			return mFormats;
		}
		
		std::string MeshConverter::getFormatsAsString(bool import_, bool export_) const{
			std::string ret;
			std::string gext = "All supported formats (";
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
			{
				if( import_ && (*i)->canImport() || export_ && (*i)->canExport() )
				{
					ret+=Lit::String(*(*i)).str();
					gext += "*."+(*i)->getExtension()+";";
				}
			}
			if( gext.empty() ) gext = "*.*";
			gext +=");;";
			return gext+ret;
		}
		const MeshConverter::Format* MeshConverter::getFormat( const std::string &ext ) const{
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
				if( (*i) && (*i)->getExtension() == ext ) return (*i);
			throw MeshFormatException( ext, "get", "format not found", EXC_LOC );
			return NULL;
		}
		MeshConverter::Format* MeshConverter::getFormat( const std::string &ext ){
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
				if( (*i) && (*i)->getExtension() == ext ) return (*i);
			throw MeshFormatException( ext, "get", "format not found", EXC_LOC );
			return NULL;
		}

		bool MeshConverter::hasFormat( const std::string &ext ) const
		{
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
				if( (*i) && (*i)->getExtension() == ext ) return true;
			return false;
		}
		MeshConverter::Format* MeshConverter::addFormat( MeshConverter::Format * fmt )
		{
			if( !fmt )
				throw NullPointer( "Invalid format pointer", EXC_LOC );
			if( hasFormat( fmt->getExtension() ) )
				throw MeshFormatException( fmt->getExtension(), "add", "format already registered", EXC_LOC );
			mFormats.push_back( fmt );
			return fmt;
		}
		bool MeshConverter::destroyFormat( const std::string &ext )
		{
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
				if( (*i) && (*i)->getExtension() == ext )
				{
					delete (*i), (*i) = NULL;
					mFormats.erase(i);
					return true;
				}
			return false;
		}
		void MeshConverter::clearFormats()
		{
			for( auto i=mFormats.begin(); i!=mFormats.end(); i++ )
				delete (*i), (*i) = NULL;
			mFormats.clear();
		}
		Ogre::MeshPtr MeshConverter::importMesh( const std::string &input_filename )
		{
			size_t extpos = input_filename.find_last_of('.');
			if( extpos == std::string::npos )
				throw MeshConverterException( input_filename, "no extension found", EXC_LOC );
			std::string ext = input_filename.substr( extpos+1, input_filename.size()-(extpos+1) );
			if( !hasFormat( ext ) )
				throw MeshConverterException( input_filename, "no format '"+ext+"' found", EXC_LOC );
			Format * fmt = getFormat(ext);
			Ogre::MeshPtr ret;
			if( fmt && fmt->canImport() )
				return fmt->importMesh( input_filename, FilePath(input_filename).fileName()+".mesh" );
			
			throw Lit::RuntimeError( Lit::EXC_RUNTIME_ERROR, "Cannot import mesh '"+input_filename+"', format '"+ext+"' cannot import meshes", EXC_LOC );
			return ret;
		}
		
		void MeshConverter::exportMesh( const std::string &output_filename, Ogre::MeshPtr mesh )
		{
			size_t extpos = output_filename.find_last_of('.');
			if( extpos == std::string::npos )
				throw MeshConverterException( output_filename, "cannot export mesh, no extension found", EXC_LOC );
			std::string ext = output_filename.substr( extpos+1, output_filename.size()-(extpos+1) );
			if( !hasFormat( ext ) )
				throw MeshConverterException( output_filename, "cannot export mesh, no format '"+ext+"' found", EXC_LOC );
			
			Format * fmt = getFormat(ext);
			if( fmt && fmt->canExport() )
			{
				fmt->exportMesh( output_filename, mesh );
				return;
			}
			throw Lit::RuntimeError( Lit::EXC_RUNTIME_ERROR, "Cannot export mesh '"+output_filename+"', format '"+ext+"' cannot export meshes", EXC_LOC );
		}
		
		LIT_API std::ostream& operator << ( std::ostream& strm, const MeshConverter::Format& fmt ){
			strm << fmt.getName() + " ( *."+fmt.getExtension()+" );;";
			return strm;
		}
	};
};